package com.dnjn.mes.biz.websocket;

import com.dnjn.mes.biz.domain.MesEquipment;
import com.dnjn.mes.biz.domain.MesWorkforceConfig;
import com.dnjn.mes.biz.domain.MesWorkforceShift;
import com.dnjn.mes.biz.domain.MesWorkforceShiftClocking;
import com.dnjn.mes.biz.domain.MesWorkforceXref;
import com.dnjn.mes.biz.service.IMesEquipmentService;
import com.dnjn.mes.biz.service.IMesWorkforceShiftClockingService;
import com.dnjn.mes.biz.service.IMesWorkforceShiftService;
import com.dnjn.mes.biz.service.IMesWorkforceXrefService;
import com.dnjn.mes.biz.service.helper.WorkShiftHelper;
import com.dnjn.mes.common.utils.spring.SpringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.websocket.EncodeException;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint(value = "/webSocket", encoders = {MesWorkforceShiftEncoder.class})
@Component
public class WebSocketServer {


    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    //在WebSocket也是这样注入，因 SpringBoot+WebSocket 对每个客户端连接都会创建一个 WebSocketServer（@ServerEndpoint 注解对应的）对象，
    // Bean 注入操作会被直接略过，因而手动注入一个全局变量

    private static final AtomicInteger OnlineCount = new AtomicInteger(0);
    // concurrent包的线程安全Set，用来存放每个客户端对应的Session对象。
    private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>();

    //private static CloudService cloudService = new CloudServiceImpl();

    @PostConstruct
    public void init() {
        log.info("websocket loading");
    }

    /**
     * 连接建立成功调用方法
     *
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) throws Exception {
        SessionSet.add(session);
        OnlineCount.incrementAndGet();  // 在线数+1
        Message message = new Message();
        message.setMsg("连接成功");
        message.setType("SUCCESS");
        MesWorkforceShiftEncoder encoder = new MesWorkforceShiftEncoder();
        SendMessage(session, message);    // 告知客户端连接成功
        //发送当前班次信息
        sendWorkforceNow(session);
        log.info("链接成功=================");
    }

    private void sendWorkforceNow(Session session) throws Exception {

        WorkShiftHelper workShiftHelper = SpringUtils.getBean("workShiftHelper");
        IMesWorkforceShiftService iMesWorkforceShiftService = SpringUtils.getBean("iMesWorkforceShiftService");
        IMesWorkforceShiftClockingService iMesWorkforceShiftClockingService = SpringUtils.getBean("iMesWorkforceShiftClockingService");
        IMesEquipmentService iMesEquipmentService = SpringUtils.getBean("iMesEquipmentService");
        IMesWorkforceXrefService iMesWorkforceXrefService = SpringUtils.getBean("iMesWorkforceXrefService");

        WorkShiftHelper.WorkShiftConf current = workShiftHelper.current();
        MesWorkforceConfig mesWorkforceConfig = current.getCurrent();
        if (null == mesWorkforceConfig) {
            log.error("获取当前班次信息失败");
            //throw new Exception();
            return;
        }
        LocalDate currentDate = LocalDateTime.now().minusHours(8).toLocalDate();
        MesWorkforceShift one = iMesWorkforceShiftService.lambdaQuery().eq(MesWorkforceShift::getWorkforceId, mesWorkforceConfig.getWorkforceId())
                .eq(MesWorkforceShift::getCurrentDate, currentDate).one();
        // 7:00
        if (null == one) {//如果没有班次记录重新将当前班次信息 写入班次记录表中
            MesEquipment mesEquipment = iMesEquipmentService.fetchCurrent();
            one = new MesWorkforceShift();
            one.setWorkforceId(mesWorkforceConfig.getWorkforceId());
            one.setCurrentDate(currentDate);
            one.setEquipmentId(mesEquipment.getEquipmentId());
            one.setWorkforceLabel(mesWorkforceConfig.getWorkforceName());
            one.setHasClockin("0");
            one.setHasClockout("0");
            iMesWorkforceShiftService.save(one);
            //将当前班次的用户列表记录到用户打卡记录表中 mes_workforce_shift_clocking
            List<MesWorkforceXref> xrefList = iMesWorkforceXrefService.lambdaQuery().eq(MesWorkforceXref::getWorkforceId, mesWorkforceConfig.getWorkforceId())
                    .eq(MesWorkforceXref::getDeleted, "0").list();
            for (MesWorkforceXref xref : xrefList) {
                MesWorkforceShiftClocking clocking = new MesWorkforceShiftClocking();
                clocking.setShiftId(one.getShiftId());
                clocking.setUserId(xref.getUserId());
                clocking.setUserName(xref.getUserName());
                clocking.setHasClockin("0");
                clocking.setHasClockout("0");
                clocking.setEquipmentId(mesEquipment.getEquipmentId());
                iMesWorkforceShiftClockingService.save(clocking);
            }
        }
        List<MesWorkforceShiftClocking> clockingList = iMesWorkforceShiftClockingService.lambdaQuery().eq(MesWorkforceShiftClocking::getShiftId, one.getShiftId()).list();
        for (MesWorkforceShiftClocking clocking : clockingList) {
            clocking.setPassword("");
        }
        one.setClockingList(clockingList);
        MesWorkforceShiftEncoder encoder = new MesWorkforceShiftEncoder();
        Message message = new Message();
        message.setData(one);
        message.setType("NOW");
        SendMessage(session, message);
    }

    /**
     * 连接关闭调用方法
     */
    @OnClose
    public void onClose(Session session) {
        //loginService.logOutAndCleanUp();
        SessionSet.remove(session);
        OnlineCount.decrementAndGet();
    }

    /**
     * 收到客户端消息后调用的方法
     */
    /*@OnMessage
    public void onMessage(MesWorkforceShift operator, Session session) {
        //SendMessage(session, "接收到消息，消息内容：" + operator);
        log.info("接收到消息，消息内容：" + operator);
        *//*if ("moveLeft".equals(operator.getOperate()))
            cloudService.moveLeft(operator.getNChannelID(), operator.getIparam2());
        if ("moveRight".equals(operator.getOperate()))
            cloudService.moveRight(operator.getNChannelID(), operator.getIparam2());
        if ("moveUp".equals(operator.getOperate()))
            cloudService.moveUp(operator.getNChannelID(), operator.getIparam2());
        if ("moveDown".equals(operator.getOperate()))
            cloudService.moveDown(operator.getNChannelID(), operator.getIparam2());*//*
    }*/

    /**
     * 出现错误
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 发送消息 实践表明 每次浏览器刷新 session会发生变化
     */
    public static void SendMessage(Session session, Message message) {
        try {
            //session.getBasicRemote().sendText(String.format("%s (From Server,Session ID=%s)", message, session.getId()));
//            session.getBasicRemote().sendText(message);
            session.getBasicRemote().sendObject(message);
        } catch (IOException | EncodeException e) {
            e.printStackTrace();
            log.error("向前端发送消息失败=========" + message);
        }
    }

    public void onMessage(MesWorkforceShift mesWorkforceShift, String type) throws EncodeException {
        for (Session session : SessionSet) {
            if (session.isOpen()) {
                MesWorkforceShiftEncoder encoder = new MesWorkforceShiftEncoder();
                Message message = new Message();
                message.setData(mesWorkforceShift);
                message.setType(type);
                SendMessage(session, message);
            }
        }
    }

    /**
     * 群发消息
     */
    /*public static void BroadCastInfo(String message) throws IOException {
        for (Session session : SessionSet) {
            if (session.isOpen())
                SendMessage(session, message);
        }
    }*/

    /**
     * 指定Session发送消息
     *
     * @param sessionId
     * @param message
     * @throws IOException
     */
    /*public static void SendMessage(String message, String sessionId) throws IOException {
        Session session = null;
        for (Session s : SessionSet) {
            if (s.getId().equals(sessionId)) {
                session = s;
                break;
            }
        }
        if (session != null)
            SendMessage(session, message);
    }*/

}
